// TODO clear cookies using CookieManager on exit
// TODO place name of currently subscribed dog on action bar
// TODO implement the floor and altitude stuff on the other screens

package com.example.fido2013;

import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.regex.Pattern;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;


import android.app.Activity;
import android.app.Dialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Address;
import android.location.Geocoder;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainMenu extends Activity {

	final Context cont = MainMenu.this;
	String sessionName;
	String sessionId;
	private String vestName;
	ArrayList<JSONObject> incidentList;
	ArrayList<JSONObject> broadcastList;
	ArrayList<JSONObject> usernameList;

	Timer timer;
	String updateInterval;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main_menu);

		Intent intent = getIntent();
		String action = intent.getAction();

		if (!action.equals(Intent.ACTION_VIEW)) {
			throw new RuntimeException("Should not happen");
		}

		Uri data = intent.getData();
		sessionName = data.getQueryParameter("sessionName");
		sessionId = data.getQueryParameter("sessionId");
		APICallAsync apiCall = new APICallAsync("http://dev.m.gatech.edu/user", sessionName, sessionId, MainMenu.this);
		String username = "";
		try {
			username = apiCall.execute().get().get(0).toString();
			System.out.println("User->" + username);

		} catch (Exception e1) {
			e1.printStackTrace();
		}

		// use the username to get the subscribed dogvest from the database and
		// set the
		// subscribed to that. Also verify if it is in the list of verified
		// usernames (from db).
		apiCall = new APICallAsync("http://dev.m.gatech.edu/d/amartin37/w/fidocpy/c/api/users/" + username, sessionName, sessionId, MainMenu.this);
		try {
			usernameList = apiCall.execute().get();
			String usernameListString = "Username list " + usernameList.toString();			
			String defVestId = "";
			System.out.println("*****");
			System.out.println((usernameList.toString()).equals("[]"));
			System.out.println();

			if ((usernameList.toString()).equals("[]")){
				System.out.println("Not a valid user");
				Intent loginIntent = new Intent(cont, LoginScreen.class);
				loginIntent.putExtra("not valid user", true);
				startActivity(loginIntent);
			}
			
			if (usernameList.size() > 0) {

				String check = usernameList.toString();
				String vestid = check.split(",")[1];
				defVestId = vestid.split("\"")[3];
			} 		
			
			System.out.println("Vest Id number is " + defVestId);
			apiCall = new APICallAsync("http://dev.m.gatech.edu/d/vkrishnan35/w/fidocpy/c/api/vests/" + defVestId, sessionName, sessionId, MainMenu.this);
			ArrayList<JSONObject> dogVestList = apiCall.execute().get();
			int numofVests = dogVestList.size();
			vestName = null;
			System.out.println("Searching for Vest Name");
			if (numofVests > 0) {
				String check = dogVestList.toString();
				vestName = check.split("\"")[3];
				if (vestName.equals("1000")) {
					vestName = "null";
				}
			} 
			
			else {
				System.out.println("Does not have a dog associated");
				vestName = null;
			}
			
			System.out.println("Vest Name is " + vestName);
			SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainMenu.this);
			SharedPreferences.Editor editor = prefs.edit();
			
			//for use in most of the rest of the app
			editor.putString("logged in user", username);
			editor.putString("subscribed dog vest", vestName);
			editor.putInt("subscribed dog vest ID", Integer.parseInt(defVestId));
			
			//for use on the settings screen when populating the default dog vest spinner
			editor.putString("default dog vest", vestName);
			editor.putInt("default dog vest ID", Integer.parseInt(defVestId));
			
			String userType = usernameList.toString().split("userType")[1].substring(3, 4);
			editor.putString("user type",  userType);
			
			editor.commit();

		} catch (Exception e) {
			e.printStackTrace();
		}

		// store cookie information
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainMenu.this);
		SharedPreferences.Editor editor = prefs.edit();
		editor.putString("sessionName", sessionName);
		editor.putString("sessionId", sessionId);
		editor.commit();

		checkForNewIncidents();
		checkForNewBroadcasts();

		int numIncidents = incidentList.size();
		int numBroadcasts = broadcastList.size();
		try {
			String oldLastIncident = incidentList.get(numIncidents - 1).get("timeFound").toString();
			String currentLastIncident = oldLastIncident;
			editor.putString("oldLastIncident", oldLastIncident);
			editor.putString("currentLastIncident", currentLastIncident);
			
			String oldLastBroadcast = broadcastList.get(numBroadcasts - 1).get("timeFound").toString();
			String currentLastBroadcast = oldLastBroadcast;
			editor.putString("oldLastBroadcast", oldLastBroadcast);
			editor.putString("currentLastBroadcast", currentLastBroadcast);
			
			editor.commit();
		} catch (JSONException e) {
			e.printStackTrace();
		}
	}
	
	public static boolean AreWeOnline(Context context) {
	      ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
	       
	      NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
	      return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
	}

	public void goToDogChoose(View view) {
		Intent i = new Intent(cont, DogChooseScreen.class);
		startActivity(i);
	}

	public void goToMap(View view) {
		Intent i = new Intent(cont, MapScreen.class);
		startActivity(i);
	}

	public void goToSettings(View view) {
		Intent i = new Intent(cont, SettingsScreen.class);
		startActivity(i);		
	}

	public void onDestroy() {
		super.onDestroy();
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainMenu.this);
		SharedPreferences.Editor editor = prefs.edit();
		editor.remove("sessionName");
		editor.remove("sessionId");
		editor.remove("subscribed dog vest");
		editor.remove("subscribed dog vest ID");
		editor.commit();
	}

	public void onPause() {
		super.onPause();
		timer.cancel();
	}
	
	public void onStop() {
		super.onStop();
		timer.cancel();
	}

	public void onResume() {
		super.onResume();
		// get currently selected dog vest
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainMenu.this);
		String currentlySelectedVest = prefs.getString("subscribed dog vest", "null");
		System.out.println(currentlySelectedVest);

		TextView currentlySelectedVestTextView = (TextView) findViewById(R.id.textView3);
		if (currentlySelectedVest.equals("null")) {
			currentlySelectedVestTextView.setText("Nothing");
		} else {
			currentlySelectedVestTextView.setText(currentlySelectedVest);
		}

		updateInterval = prefs.getString("update interval", "null");
		if (updateInterval.equals("null")) {
			updateInterval = "10000";
		} else if (updateInterval.substring(3).equals("min")) {
			int tempInt = Integer.parseInt(updateInterval.substring(0, 2));
			tempInt = tempInt * 60 * 1000;
			updateInterval = Integer.toString(tempInt);
			System.out.println(updateInterval);
		} else {
			updateInterval = updateInterval.substring(0, 2).trim() + "000";
			System.out.println(updateInterval);
		}

		startCheckingIncidents();
	}
	
	// TODO put a bunch of this in its own class to cut down on copied code
	
	public void startCheckingIncidents() { 
		timer = new Timer();
		timer.scheduleAtFixedRate(new TimerTask() {

			public void run() {
				if (AreWeOnline(MainMenu.this)) {					
					SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainMenu.this);
					SharedPreferences.Editor editor = prefs.edit();
					String oldLastIncident = prefs.getString("oldLastIncident", "null");
					String currentLastIncident = prefs.getString("currentLastIncident", "null");
	
					String incidentDog = "";
					String currentlySelectedVest = prefs.getString("subscribed dog vest", "null");
					final int currentlySelectedVestID = prefs.getInt("subscribed dog vest ID", 1000);
	
					final ArrayList<JSONObject> thisIncidentList = new APICallIncidentsNoAsync(sessionName, sessionId).checkForNewIncidentsNoAsync();
					final int numIncidents = thisIncidentList.size();
					try {
						currentLastIncident = thisIncidentList.get(numIncidents - 1).get("timeFound").toString(); 
						incidentDog = thisIncidentList.get(numIncidents - 1).get("dogvest").toString();
					} catch (JSONException e) {
						e.printStackTrace();
					}
					if (currentLastIncident.equals(oldLastIncident)) {
						System.out.println("no new incident found");
					} else if (!currentLastIncident.equals(oldLastIncident) && (!incidentDog.equals(currentlySelectedVest))) {
						oldLastIncident = currentLastIncident;
						editor.putString("oldLastIncident", oldLastIncident);
						editor.putString("currentLastIncident", currentLastIncident);
						editor.commit();
						System.out.println("new incident found, but not the right vest");
					} else if (!currentLastIncident.equals(oldLastIncident) && (incidentDog.equals(currentlySelectedVest))) {
						oldLastIncident = currentLastIncident;
						editor.putString("oldLastIncident", oldLastIncident);
						editor.putString("currentLastIncident", currentLastIncident);
						editor.commit();
						System.out.println("new incident found and is the right vest");
						try {
							final String latitude = thisIncidentList.get(numIncidents - 1).get("latitude").toString();
							final String longitude = thisIncidentList.get(numIncidents - 1).get("longitude").toString();
							final String bombType = thisIncidentList.get(numIncidents - 1).get("bombType").toString();
							final String bombIsActive = thisIncidentList.get(numIncidents - 1).get("bombIsActive").toString();
							
							final String dogID = thisIncidentList.get(numIncidents - 1).get("dogID").toString();
							final String dogvest = thisIncidentList.get(numIncidents - 1).get("dogvest").toString();
							final String timeFound = thisIncidentList.get(numIncidents - 1).get("timeFound").toString();
	
							MainMenu.this.runOnUiThread(new Runnable() {
								public void run() {
									APICallDogVestsAsync dogDetails = new APICallDogVestsAsync(sessionName, sessionId, currentlySelectedVestID);
									String dogFloor = "-1";
									try {
										JSONObject dogDetailsObject = null;
										try {
											dogDetailsObject = dogDetails.execute().get();
										} catch (InterruptedException e) {
											e.printStackTrace();
										} catch (ExecutionException e) {
											e.printStackTrace();
										}									
										dogFloor = dogDetailsObject.getString("altitude");
										System.out.println(dogFloor);
									} catch (JSONException e1) {
										e1.printStackTrace();
									}
									showIncidentDialog(false, latitude, longitude, bombType, bombIsActive, dogID, dogvest, timeFound, dogFloor);
								}
							});
						} catch (JSONException e) {
							e.printStackTrace();
						}
					}					
										
					String oldLastBroadcast = prefs.getString("oldLastBroadcast", "null");
					String currentLastBroadcast = prefs.getString("currentLastBroadcast", "null");
					String myUserType = prefs.getString("user type", "P");
					String broadcastDog = "";
					String broadcastDogID = "";
					
					String userType = null;
					
					final ArrayList<JSONObject> thisBroadcastList = new APICallBroadcastsNoAsync(sessionName, sessionId).checkForNewBroadcastsNoAsync();
					final int numBroadcasts = thisBroadcastList.size();
					try {
						currentLastBroadcast = thisBroadcastList.get(numBroadcasts - 1).get("timeFound").toString(); 
						broadcastDog = thisBroadcastList.get(numBroadcasts - 1).get("dogvest").toString();
						broadcastDogID = thisBroadcastList.get(numBroadcasts - 1).get("dogID").toString();
						userType = thisBroadcastList.get(numBroadcasts - 1).get("userType").toString();
					} catch (JSONException e) {
						e.printStackTrace();
					}
					
					final int broadcastDogIDInt = Integer.parseInt(broadcastDogID);
					
					boolean myUserTypePresent = userType.contains(myUserType);
					
					if (currentLastBroadcast.equals(oldLastBroadcast)) {
						System.out.println("no new broadcast found");
					} else if (!currentLastBroadcast.equals(oldLastBroadcast) && (broadcastDog.equals(currentlySelectedVest))) {
						oldLastBroadcast = currentLastBroadcast;
						editor.putString("oldLastBroadcast", oldLastBroadcast);
						editor.putString("currentLastBroadcast", currentLastBroadcast);
						editor.commit();
						System.out.println("new broadcast found, but it was from this vest");
					} else if (!currentLastBroadcast.equals(oldLastBroadcast) && !myUserTypePresent) {
							oldLastBroadcast = currentLastBroadcast;
							editor.putString("oldLastBroadcast", oldLastBroadcast);
							editor.putString("currentLastBroadcast", currentLastBroadcast);
							editor.commit();
							System.out.println("new broadcast found, but it was not the right user type");
					} else if (!currentLastBroadcast.equals(oldLastBroadcast) && (!broadcastDog.equals(currentlySelectedVest)) && myUserTypePresent) {
						oldLastBroadcast = currentLastBroadcast;
						editor.putString("oldLastBroadcast", oldLastBroadcast);
						editor.putString("currentLastBroadcast", currentLastBroadcast);
						editor.commit();
						System.out.println("new broadcast found and is not from this vest");
						String showBroadcasts = prefs.getString("show broadcasts", "true");
						if (showBroadcasts.equals("true")) {
							try {
								final String latitude = thisBroadcastList.get(numBroadcasts - 1).get("latitude").toString();
								final String longitude = thisBroadcastList.get(numBroadcasts - 1).get("longitude").toString();
								final String bombType = thisBroadcastList.get(numBroadcasts - 1).get("bombType").toString();
								final String bombIsActive = thisBroadcastList.get(numBroadcasts - 1).get("bombIsActive").toString();
								
								final String dogID = thisBroadcastList.get(numBroadcasts - 1).get("dogID").toString();
								final String dogvest = thisBroadcastList.get(numBroadcasts - 1).get("dogvest").toString();
								final String timeFound = thisBroadcastList.get(numBroadcasts - 1).get("timeFound").toString();
		
								MainMenu.this.runOnUiThread(new Runnable() {
									public void run() {
										APICallDogVestsAsync dogDetails = new APICallDogVestsAsync(sessionName, sessionId, broadcastDogIDInt);
										String dogFloor = "-1";
										try {
											JSONObject dogDetailsObject = null;
											try {
												dogDetailsObject = dogDetails.execute().get();
											} catch (InterruptedException e) {
												e.printStackTrace();
											} catch (ExecutionException e) {
												e.printStackTrace();
											}									
											dogFloor = dogDetailsObject.getString("altitude");
											System.out.println(dogFloor);
										} catch (JSONException e1) {
											e1.printStackTrace();
										}
										showIncidentDialog(true, latitude, longitude, bombType, bombIsActive, dogID, dogvest, timeFound, dogFloor);
									}
								});
							} catch (JSONException e) {
								e.printStackTrace();
							}
						}
						else if (showBroadcasts.equals("false")) {
							System.out.println("found a broadcast, but I'm not supposed to show it");
						}
					}					
				}
				
				if (!AreWeOnline(MainMenu.this)) {
					runOnUiThread(new Runnable() {
					    public void run() {
					    	Toast.makeText(getBaseContext(), "No network connectivity detected. Please make sure WiFi or 3G/4G data network is available.", Toast.LENGTH_LONG).show();
					    }
					});		        	
		        }
			}
		}, 0, Integer.parseInt(updateInterval));
	}

	public void checkForNewIncidents() {
		APICallAsync apiCall = new APICallAsync("http://dev.m.gatech.edu/d/sraghu3/w/fidocpy/c/api/incident", sessionName, sessionId, MainMenu.this);
		try {
			incidentList = apiCall.execute().get();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
	}
	
	public void checkForNewBroadcasts() {
		APICallAsync apiCall = new APICallAsync("http://dev.m.gatech.edu/d/amartin37/w/fidocpy/c/api/broadcast", sessionName, sessionId, MainMenu.this);
		try {
			broadcastList = apiCall.execute().get();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
	}

	public void showIncidentDialog(boolean isBroadcast, final String lat, final String lon, final String bombType, final String isActive, final String dogID, final String dogvest, final String timeFound, String floor) {		
		final Dialog dialog = new Dialog(MainMenu.this);
		LayoutInflater inflater = MainMenu.this.getLayoutInflater();

		View dialogView = inflater.inflate(R.layout.custom_dialog_box, null);
		dialog.setContentView(dialogView);

		Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
		v.vibrate(500);

		if (!isBroadcast) {
			dialog.setTitle("New Threat Detected.");
		}
		else {
			dialog.setTitle("New Broadcast.");
		}		
		
		TextView bombTypeTextView = (TextView) dialogView.findViewById(R.id.bombTypeTextView);
		TextView activeOrNotTextView = (TextView) dialogView.findViewById(R.id.bombStatusTextView);
		TextView addressLine1TextView = (TextView) dialogView.findViewById(R.id.bombAddressTextViewLine1);
		TextView floorTextView = (TextView) dialogView.findViewById(R.id.textView4);

		bombTypeTextView.setText(bombType);

		if (isActive.equals("Y")) {
			activeOrNotTextView.setText("Active");
		} 
		else {
			activeOrNotTextView.setText("Innactive");
		}
		
		String address = getAddress(Float.parseFloat(lat), Float.parseFloat(lon));
		int breakIndex = address.indexOf("\n");
		addressLine1TextView.setText(address);
		
		Notification n  = new Notification.Builder(this)
        .setContentTitle("New " + bombType + " bomb found at " + address)
        .setSmallIcon(R.drawable.dog)
        .setAutoCancel(true)
        .build();    
				
		NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		notificationManager.notify(0, n);
		
		if (floor.equals("-1")) {
			floorTextView.setText("N/A");
		}
		else {
			floorTextView.setText(floor);
		}

		Button navigateButton = (Button) dialog.findViewById(R.id.navigateButton);
		navigateButton.setText("Map");
		navigateButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				
				Intent i = new Intent(cont, MapScreen.class);
				i.putExtra("latitude", Double.parseDouble(lat));
				i.putExtra("longitude", Double.parseDouble(lon));
				startActivity(i);
				dialog.dismiss();
			}
		});

		Button broadcastAlertButton = (Button) dialog.findViewById(R.id.broadcastAlertButton);
		broadcastAlertButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {					
				Intent broadcastIntent = new Intent(cont, BroadcastChoiceScreen.class);
				broadcastIntent.putExtra("lat", lat);
				broadcastIntent.putExtra("lon", lon);
				broadcastIntent.putExtra("bombType", bombType);
				broadcastIntent.putExtra("isActive", isActive);
				broadcastIntent.putExtra("dogID", dogID);
				broadcastIntent.putExtra("dogvest", dogvest);
				broadcastIntent.putExtra("alerting activity", "MainMenu");
				
				dialog.dismiss();
				
				startActivity(broadcastIntent);		
			}
		});

		Button dismissButton = (Button) dialog.findViewById(R.id.dismissButton);
		dismissButton.setText("  Dismiss Alert ");
		dismissButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				dialog.dismiss();
			}
		});

		dialog.show();
		
		if (isBroadcast) {
			broadcastAlertButton.setEnabled(false);
		}
		else {
			broadcastAlertButton.setEnabled(true);
		}
		
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainMenu.this);
		String displayTimeMinutes = prefs.getString("display time minutes", "null");
		String displayTimeSeconds = prefs.getString("display time seconds", "null");
		
		int displayTimeMinutesInt;
		int displayTimeSecondsInt;
		
		if (displayTimeMinutes.equals("null") || displayTimeMinutes.equals("")) {
			displayTimeMinutesInt = 0;
		}
		else {
			displayTimeMinutesInt = Integer.parseInt(displayTimeMinutes);
		}
		
		if (displayTimeSeconds.equals("null") || displayTimeSeconds.equals("")) {
			displayTimeSecondsInt = 0;
		}
		else {
			displayTimeSecondsInt = Integer.parseInt(displayTimeSeconds);
		}		
		
		int totalTimeToDisplay = (((displayTimeMinutesInt * 60) + displayTimeSecondsInt)) * 1000;
		
		if (displayTimeMinutesInt != 0 || displayTimeSecondsInt != 0) {
			Timer dialogTimer = new Timer();
			dialogTimer.schedule(new TimerTask() {
				
				public void run() {
					dialog.dismiss();
				}
				
			}, totalTimeToDisplay);
		}
	}

	private String getAddress(double latitude, double longitude) {		
		StringBuilder result = new StringBuilder();
		try {
			Geocoder geocoder = new Geocoder(this, Locale.getDefault());
			List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
			if (addresses.size() > 0) {
				Address address = addresses.get(0);
				result.append(address.getAddressLine(0)).append("\n");
				result.append(address.getLocality()).append(", " + address.getAdminArea()).append("\n");
			}
		} catch (IOException e) {
			Log.e("tag", e.getMessage());
		}

		return result.toString();
	}
}
